﻿Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.ComponentModel.Design.Serialization
Imports System.Reflection
Imports System.Runtime.CompilerServices
Imports System.Workflow.ComponentModel.Serialization

Namespace System.Workflow.ComponentModel
    <DesignerSerializer(GetType(ActivityCollectionMarkupSerializer), GetType(WorkflowMarkupSerializer)), DefaultMember("Item")> _
    Public NotInheritable Class ActivityCollection
        Inherits List([Of] Activity)
        Implements IList([Of] Activity), ICollection([Of] Activity), IEnumerable([Of] Activity), IList, ICollection, IEnumerable
        ' Events
        Public Custom Event ListChanged As EventHandler([Of] ActivityCollectionChangeEventArgs)
        Friend Custom Event ListChanging As EventHandler([Of] ActivityCollectionChangeEventArgs)

        ' Methods
        Public Sub New(ByVal owner As Activity)
            If (owner Is Nothing) Then
                Throw New ArgumentNullException("owner")
            End If
            If (owner Is Nothing) Then
                Throw New ArgumentException(SR.GetString("Error_UnexpectedArgumentType", New Object() { GetType(Activity).FullName }), "owner")
            End If
            Me.owner = owner
        End Sub

        Public Sub Add(ByVal item As Activity)
            DirectCast(Me, ICollection([Of] Activity)).Add(item)
        End Sub

        Public Sub Clear()
            DirectCast(Me, ICollection([Of] Activity)).Clear
        End Sub

        Public Function Contains(ByVal item As Activity) As Boolean
            Return DirectCast(Me, ICollection([Of] Activity)).Contains(item)
        End Function

        Private Sub FireListChanged(ByVal eventArgs As ActivityCollectionChangeEventArgs)
            If (Not Me.ListChanged Is Nothing) Then
                Me.ListChanged.Invoke(Me, eventArgs)
            End If
        End Sub

        Private Sub FireListChanging(ByVal eventArgs As ActivityCollectionChangeEventArgs)
            If (Not Me.ListChanging Is Nothing) Then
                Me.ListChanging.Invoke(Me, eventArgs)
            End If
        End Sub

        Public Function GetEnumerator() As IEnumerator([Of] Activity)
            Return DirectCast(Me, IEnumerable([Of] Activity)).GetEnumerator
        End Function

        Public Function IndexOf(ByVal item As Activity) As Integer
            Return DirectCast(Me, IList([Of] Activity)).IndexOf(item)
        End Function

        Friend Sub InnerAdd(ByVal activity As Activity)
            MyBase.Add(activity)
        End Sub

        Public Sub Insert(ByVal index As Integer, ByVal item As Activity)
            DirectCast(Me, IList([Of] Activity)).Insert(index, item)
        End Sub

        Public Function Remove(ByVal item As Activity) As Boolean
            Return DirectCast(Me, ICollection([Of] Activity)).Remove(item)
        End Function

        Public Sub RemoveAt(ByVal index As Integer)
            DirectCast(Me, IList([Of] Activity)).RemoveAt(index)
        End Sub

        Private Sub System.Collections.Generic.ICollection<System.Workflow.ComponentModel.Activity>.Add(ByVal item As Activity) Implements ICollection([Of] Activity).Add
            If (item Is Nothing) Then
                Throw New ArgumentNullException("item")
            End If
            Dim eventArgs As New ActivityCollectionChangeEventArgs(MyBase.Count, Nothing, item, Me.owner, ActivityCollectionChangeAction.Add)
            Me.FireListChanging(eventArgs)
            MyBase.Add(item)
            Me.FireListChanged(eventArgs)
        End Sub

        Private Sub System.Collections.Generic.ICollection<System.Workflow.ComponentModel.Activity>.Clear() Implements ICollection([Of] Activity).Clear
            Dim range As ICollection([Of] Activity) = MyBase.GetRange(0, MyBase.Count)
            Dim eventArgs As New ActivityCollectionChangeEventArgs(-1, range, Nothing, Me.owner, ActivityCollectionChangeAction.Remove)
            Me.FireListChanging(eventArgs)
            MyBase.Clear
            Me.FireListChanged(eventArgs)
        End Sub

        Private Function System.Collections.Generic.ICollection<System.Workflow.ComponentModel.Activity>.Contains(ByVal item As Activity) As Boolean Implements ICollection([Of] Activity).Contains
            Return MyBase.Contains(item)
        End Function

        Private Sub System.Collections.Generic.ICollection<System.Workflow.ComponentModel.Activity>.CopyTo(ByVal array As Activity(), ByVal arrayIndex As Integer) Implements ICollection([Of] Activity).CopyTo
            MyBase.CopyTo(array, arrayIndex)
        End Sub

        Private Function System.Collections.Generic.ICollection<System.Workflow.ComponentModel.Activity>.Remove(ByVal item As Activity) As Boolean Implements ICollection([Of] Activity).Remove
            If MyBase.Contains(item) Then
                Dim index As Integer = MyBase.IndexOf(item)
                If (index >= 0) Then
                    Dim eventArgs As New ActivityCollectionChangeEventArgs(index, item, Nothing, Me.owner, ActivityCollectionChangeAction.Remove)
                    Me.FireListChanging(eventArgs)
                    MyBase.Remove(item)
                    Me.FireListChanged(eventArgs)
                    Return True
                End If
            End If
            Return False
        End Function

        Private Function System.Collections.Generic.IEnumerable<System.Workflow.ComponentModel.Activity>.GetEnumerator() As IEnumerator([Of] Activity) Implements IEnumerable([Of] Activity).GetEnumerator
            Return MyBase.GetEnumerator
        End Function

        Private Function System.Collections.Generic.IList<System.Workflow.ComponentModel.Activity>.IndexOf(ByVal item As Activity) As Integer Implements IList([Of] Activity).IndexOf
            Return MyBase.IndexOf(item)
        End Function

        Private Sub System.Collections.Generic.IList<System.Workflow.ComponentModel.Activity>.Insert(ByVal index As Integer, ByVal item As Activity) Implements IList([Of] Activity).Insert
            If ((index < 0) OrElse (index > MyBase.Count)) Then
                Throw New ArgumentOutOfRangeException("index")
            End If
            If (item Is Nothing) Then
                Throw New ArgumentNullException("item")
            End If
            Dim eventArgs As New ActivityCollectionChangeEventArgs(index, Nothing, item, Me.owner, ActivityCollectionChangeAction.Add)
            Me.FireListChanging(eventArgs)
            MyBase.Insert(index, item)
            Me.FireListChanged(eventArgs)
        End Sub

        Private Sub System.Collections.Generic.IList<System.Workflow.ComponentModel.Activity>.RemoveAt(ByVal index As Integer) Implements IList([Of] Activity).RemoveAt
            If ((index < 0) OrElse (index >= MyBase.Count)) Then
                Throw New ArgumentOutOfRangeException("Index")
            End If
            Dim removedActivity As Activity = MyBase.Item(index)
            Dim eventArgs As New ActivityCollectionChangeEventArgs(index, removedActivity, Nothing, Me.owner, ActivityCollectionChangeAction.Remove)
            Me.FireListChanging(eventArgs)
            MyBase.RemoveAt(index)
            Me.FireListChanged(eventArgs)
        End Sub

        Private Sub System.Collections.ICollection.CopyTo(ByVal array As Array, ByVal index As Integer) Implements ICollection.CopyTo
            Dim i As Integer
            For i = 0 To Me.Count - 1
                array.SetValue(Me.Item(i), CInt((i + index)))
            Next i
        End Sub

        Private Function System.Collections.IEnumerable.GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
            Return DirectCast(Me, IEnumerable([Of] Activity)).GetEnumerator
        End Function

        Private Function System.Collections.IList.Add(ByVal value As Object) As Integer Implements IList.Add
            If Not TypeOf value Is Activity Then
                Throw New Exception(SR.GetString("Error_InvalidListItem", New Object() { MyBase.GetType.GetGenericArguments(0).FullName }))
            End If
            DirectCast(Me, ICollection([Of] Activity)).Add(DirectCast(value, Activity))
            Return (Me.Count - 1)
        End Function

        Private Sub System.Collections.IList.Clear() Implements IList.Clear
            DirectCast(Me, ICollection([Of] Activity)).Clear
        End Sub

        Private Function System.Collections.IList.Contains(ByVal value As Object) As Boolean Implements IList.Contains
            If Not TypeOf value Is Activity Then
                Throw New Exception(SR.GetString("Error_InvalidListItem", New Object() { MyBase.GetType.GetGenericArguments(0).FullName }))
            End If
            Return DirectCast(Me, ICollection([Of] Activity)).Contains(DirectCast(value, Activity))
        End Function

        Private Function System.Collections.IList.IndexOf(ByVal value As Object) As Integer Implements IList.IndexOf
            If Not TypeOf value Is Activity Then
                Throw New Exception(SR.GetString("Error_InvalidListItem", New Object() { MyBase.GetType.GetGenericArguments(0).FullName }))
            End If
            Return DirectCast(Me, IList([Of] Activity)).IndexOf(DirectCast(value, Activity))
        End Function

        Private Sub System.Collections.IList.Insert(ByVal index As Integer, ByVal value As Object) Implements IList.Insert
            If Not TypeOf value Is Activity Then
                Throw New Exception(SR.GetString("Error_InvalidListItem", New Object() { MyBase.GetType.GetGenericArguments(0).FullName }))
            End If
            DirectCast(Me, IList([Of] Activity)).Insert(index, DirectCast(value, Activity))
        End Sub

        Private Sub System.Collections.IList.Remove(ByVal value As Object) Implements IList.Remove
            If Not TypeOf value Is Activity Then
                Throw New Exception(SR.GetString("Error_InvalidListItem", New Object() { MyBase.GetType.GetGenericArguments(0).FullName }))
            End If
            DirectCast(Me, ICollection([Of] Activity)).Remove(DirectCast(value, Activity))
        End Sub


        ' Properties
        Public ReadOnly Property Count As Integer
            Get
                Return Me.Count
            End Get
        End Property

        Public Default Property Item(ByVal index As Integer) As Activity
            Get
                Return Me.Item(index)
            End Get
            Set(ByVal value As Activity)
                Me.Item(index) = value
            End Set
        End Property

        Public ReadOnly Default Property Item(ByVal key As String) As Activity
            Get
                Dim i As Integer
                For i = 0 To Me.Count - 1
                    If (Me.Item(i).Name.Equals(key) OrElse Me.Item(i).QualifiedName.Equals(key)) Then
                        Return Me.Item(i)
                    End If
                Next i
                Return Nothing
            End Get
        End Property

        Friend ReadOnly Property Owner As Activity
            Get
                Return Me.owner
            End Get
        End Property

        Private ReadOnly Property System.Collections.Generic.ICollection<System.Workflow.ComponentModel.Activity>.Count As Integer
            Get
                Return MyBase.Count
            End Get
        End Property

        Private ReadOnly Property System.Collections.Generic.ICollection<System.Workflow.ComponentModel.Activity>.IsReadOnly As Boolean
            Get
                Return False
            End Get
        End Property

        Private Property System.Collections.Generic.IList<System.Workflow.ComponentModel.Activity>.Item(ByVal index As Integer) As Activity
            Get
                Return MyBase.Item(index)
            End Get
            Set(ByVal value As Activity)
                If (value Is Nothing) Then
                    Throw New ArgumentNullException("item")
                End If
                Dim removedActivity As Activity = MyBase.Item(index)
                Dim eventArgs As New ActivityCollectionChangeEventArgs(index, removedActivity, value, Me.owner, ActivityCollectionChangeAction.Replace)
                Me.FireListChanging(eventArgs)
                MyBase.Item(index) = value
                Me.FireListChanged(eventArgs)
            End Set
        End Property

        Private ReadOnly Property System.Collections.ICollection.IsSynchronized As Boolean
            Get
                Return False
            End Get
        End Property

        Private ReadOnly Property System.Collections.ICollection.SyncRoot As Object
            Get
                Return Me
            End Get
        End Property

        Private ReadOnly Property System.Collections.IList.IsFixedSize As Boolean
            Get
                Return False
            End Get
        End Property

        Private ReadOnly Property System.Collections.IList.IsReadOnly As Boolean
            Get
                Return Me.IsReadOnly
            End Get
        End Property

        Private Property System.Collections.IList.Item(ByVal index As Integer) As Object
            Get
                Return Me.Item(index)
            End Get
            Set(ByVal value As Object)
                If Not TypeOf value Is Activity Then
                    Throw New Exception(SR.GetString("Error_InvalidListItem", New Object() { MyBase.GetType.GetGenericArguments(0).FullName }))
                End If
                Me.Item(index) = DirectCast(value, Activity)
            End Set
        End Property


        ' Fields
        Private owner As Activity
    End Class
End Namespace

